﻿// ControlPointDlg.cpp: 实现文件
//

#include "pch.h"
#include "ControlPointDlg.h"
#include "afxdialogex.h"


// ControlPointDlg 对话框

IMPLEMENT_DYNAMIC(ControlPointDlg, CDialogEx)

ControlPointDlg::ControlPointDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG_GCP, pParent)
{

}

ControlPointDlg::~ControlPointDlg()
{
}

void ControlPointDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_POINT, m_PointList);
	DDX_Control(pDX, IDC_COMBO_DEGREE, m_Combo);
}


BEGIN_MESSAGE_MAP(ControlPointDlg, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON_ADDPOINT, &ControlPointDlg::OnBnClickedButtonAddpoint)
	ON_BN_CLICKED(IDC_BUTTON_DELETEPOINT, &ControlPointDlg::OnBnClickedButtonDeletepoint)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_POINT, &ControlPointDlg::OnItemchangedListPoint)
	ON_BN_CLICKED(IDC_BUTTON_PREDICT, &ControlPointDlg::OnBnClickedButtonPredict)
	ON_CBN_SELCHANGE(IDC_COMBO_DEGREE, &ControlPointDlg::OnSelchangeComboDegree)
	ON_COMMAND(ID_CPFILEOUT, &ControlPointDlg::OnCpfileout)
	ON_COMMAND(ID_INPUTCONPOINT, &ControlPointDlg::OnInputconpoint)
	ON_COMMAND(ID_OUTPUTCONPOINT, &ControlPointDlg::OnOutputconpoint)
	ON_COMMAND(ID_ADDCONPOINT, &ControlPointDlg::OnAddconpoint)
END_MESSAGE_MAP()


// ControlPointDlg 消息处理程序


BOOL ControlPointDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	m_Menu.LoadMenu(IDR_MENU3);
	m_PointList.SetExtendedStyle(m_PointList.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	SetMenu(&m_Menu);

	iItemNum = -1;
	nIndex = 0;
	// TODO:  在此添加额外的初始化
	m_PointList.InsertColumn(0, _T("No."), LVCFMT_LEFT, 40, -1);
	m_PointList.InsertColumn(1, _T("Base X"), LVCFMT_LEFT, 55, -1);
	m_PointList.InsertColumn(2, _T("Base Y"), LVCFMT_LEFT, 55, -1);
	m_PointList.InsertColumn(3, _T("Warp X"), LVCFMT_LEFT, 55, -1);
	m_PointList.InsertColumn(4, _T("Warp Y"), LVCFMT_LEFT, 55, -1);
	m_PointList.InsertColumn(5, _T("Pre X"), LVCFMT_LEFT, 50, -1);
	m_PointList.InsertColumn(6, _T("Pre Y"), LVCFMT_LEFT, 50, -1);
	m_PointList.InsertColumn(7, _T("Error X"), LVCFMT_LEFT, 55, -1);
	m_PointList.InsertColumn(8, _T("Error X"), LVCFMT_LEFT, 55, -1);
	m_PointList.InsertColumn(9, _T("RMS"), LVCFMT_LEFT, 47, -1);

	m_PointList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);

	m_Combo.AddString(_T("1"));
	m_Combo.AddString(_T("2"));
	m_Combo.AddString(_T("3"));

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}


void ControlPointDlg::OnBnClickedButtonAddpoint()
{
	m_pPointController->GetPoint();

	DisplayPoint();
	// TODO: 在此添加控件通知处理程序代码
}


void ControlPointDlg::OnBnClickedButtonDeletepoint()
{
	if(iItemNum >= 0)
		m_pPointController->DeletePoint(iItemNum);

	DisplayPoint();
	// TODO: 在此添加控件通知处理程序代码
}

void ControlPointDlg::DisplayPoint()
{
	m_PointList.DeleteAllItems();
	m_pPointController->nIndex = nIndex + 1;
	if (nIndex == 0)
	{
		if (m_pPointController->m_ControlPointList.size() < 3)
		{
			for (int ii = 0; ii < m_pPointController->m_ControlPointList.size(); ii++)
			{
				CString strNum, strBaseX, strBaseY, strWarpX, strWarpY;
				strNum.Format(_T("%d"), ii + 1);
				strBaseX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.x);
				strBaseY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.y);
				strWarpX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.x);
				strWarpY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.y);
				m_PointList.InsertItem(ii, strNum);
				m_PointList.SetItemText(ii, 1, strBaseX);
				m_PointList.SetItemText(ii, 2, strBaseY);
				m_PointList.SetItemText(ii, 3, strWarpX);
				m_PointList.SetItemText(ii, 4, strWarpY);
				m_PointList.SetItemText(ii, 5, _T("/"));
				m_PointList.SetItemText(ii, 6, _T("/"));
				m_PointList.SetItemText(ii, 7, _T("/"));
				m_PointList.SetItemText(ii, 8, _T("/"));
				m_PointList.SetItemText(ii, 9, _T("/"));
			}
		}
		else if (m_pPointController->m_ControlPointList.size() >= 3)
		{
			m_pPointController->CalculateLSM(1);

			for (int ii = 0; ii < m_pPointController->m_ControlPointList.size(); ii++)
			{
				CString strNum, strBaseX, strBaseY, strWarpX, strWarpY, strPreX, strPreY, strErrorX, strErrorY, strError;
				strNum.Format(_T("%d"), ii + 1);
				strBaseX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.x);
				strBaseY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.y);
				strWarpX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.x);
				strWarpY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.y);

				double dPreX = 0;
				double dPreY = 0;

				m_pPointController->CalculatePre(m_pPointController->m_ControlPointList[ii].BasePoint, dPreX, dPreY, 1);

				double dErrorX = dPreX - m_pPointController->m_ControlPointList[ii].WarpPoint.x;
				double dErrorY = dPreY - m_pPointController->m_ControlPointList[ii].WarpPoint.y;

				strPreX.Format(_T("%.2f"), dPreX);
				strPreY.Format(_T("%.2f"), dPreY);

				strErrorX.Format(_T("%.2f"), dErrorX);
				strErrorY.Format(_T("%.2f"), dErrorY);

				strError.Format(_T("%.2f"), sqrt(dErrorX * dErrorX + dErrorY * dErrorY));

				m_PointList.InsertItem(ii, strNum);
				m_PointList.SetItemText(ii, 1, strBaseX);
				m_PointList.SetItemText(ii, 2, strBaseY);
				m_PointList.SetItemText(ii, 3, strWarpX);
				m_PointList.SetItemText(ii, 4, strWarpY);
				m_PointList.SetItemText(ii, 5, strPreX);
				m_PointList.SetItemText(ii, 6, strPreY);
				m_PointList.SetItemText(ii, 7, strErrorX);
				m_PointList.SetItemText(ii, 8, strErrorY);
				m_PointList.SetItemText(ii, 9, strError);
			}
		}
	}
	else if (nIndex == 1)
	{
		if (m_pPointController->m_ControlPointList.size() < 6)
		{
			for (int ii = 0; ii < m_pPointController->m_ControlPointList.size(); ii++)
			{
				CString strNum, strBaseX, strBaseY, strWarpX, strWarpY;
				strNum.Format(_T("%d"), ii + 1);
				strBaseX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.x);
				strBaseY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.y);
				strWarpX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.x);
				strWarpY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.y);
				m_PointList.InsertItem(ii, strNum);
				m_PointList.SetItemText(ii, 1, strBaseX);
				m_PointList.SetItemText(ii, 2, strBaseY);
				m_PointList.SetItemText(ii, 3, strWarpX);
				m_PointList.SetItemText(ii, 4, strWarpY);
				m_PointList.SetItemText(ii, 5, _T("/"));
				m_PointList.SetItemText(ii, 6, _T("/"));
				m_PointList.SetItemText(ii, 7, _T("/"));
				m_PointList.SetItemText(ii, 8, _T("/"));
				m_PointList.SetItemText(ii, 9, _T("/"));
			}
		}
		else if (m_pPointController->m_ControlPointList.size() >= 6)
		{
			m_pPointController->CalculateLSM(2);

			for (int ii = 0; ii < m_pPointController->m_ControlPointList.size(); ii++)
			{
				CString strNum, strBaseX, strBaseY, strWarpX, strWarpY, strPreX, strPreY, strErrorX, strErrorY, strError;
				strNum.Format(_T("%d"), ii + 1);
				strBaseX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.x);
				strBaseY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.y);
				strWarpX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.x);
				strWarpY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.y);

				double dPreX = 0;
				double dPreY = 0;

				m_pPointController->CalculatePre(m_pPointController->m_ControlPointList[ii].BasePoint, dPreX, dPreY, 2);

				double dErrorX = dPreX - m_pPointController->m_ControlPointList[ii].WarpPoint.x;
				double dErrorY = dPreY - m_pPointController->m_ControlPointList[ii].WarpPoint.y;

				strPreX.Format(_T("%.2f"), dPreX);
				strPreY.Format(_T("%.2f"), dPreY);

				strErrorX.Format(_T("%.2f"), dErrorX);
				strErrorY.Format(_T("%.2f"), dErrorY);

				strError.Format(_T("%.2f"), sqrt(dErrorX * dErrorX + dErrorY * dErrorY));

				m_PointList.InsertItem(ii, strNum);
				m_PointList.SetItemText(ii, 1, strBaseX);
				m_PointList.SetItemText(ii, 2, strBaseY);
				m_PointList.SetItemText(ii, 3, strWarpX);
				m_PointList.SetItemText(ii, 4, strWarpY);
				m_PointList.SetItemText(ii, 5, strPreX);
				m_PointList.SetItemText(ii, 6, strPreY);
				m_PointList.SetItemText(ii, 7, strErrorX);
				m_PointList.SetItemText(ii, 8, strErrorY);
				m_PointList.SetItemText(ii, 9, strError);
			}
		}
	}
	else if (nIndex == 2)
	{
		if (m_pPointController->m_ControlPointList.size() < 10)
		{
			for (int ii = 0; ii < m_pPointController->m_ControlPointList.size(); ii++)
			{
				CString strNum, strBaseX, strBaseY, strWarpX, strWarpY;
				strNum.Format(_T("%d"), ii + 1);
				strBaseX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.x);
				strBaseY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.y);
				strWarpX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.x);
				strWarpY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.y);
				m_PointList.InsertItem(ii, strNum);
				m_PointList.SetItemText(ii, 1, strBaseX);
				m_PointList.SetItemText(ii, 2, strBaseY);
				m_PointList.SetItemText(ii, 3, strWarpX);
				m_PointList.SetItemText(ii, 4, strWarpY);
				m_PointList.SetItemText(ii, 5, _T("/"));
				m_PointList.SetItemText(ii, 6, _T("/"));
				m_PointList.SetItemText(ii, 7, _T("/"));
				m_PointList.SetItemText(ii, 8, _T("/"));
				m_PointList.SetItemText(ii, 9, _T("/"));
			}
		}
		else if (m_pPointController->m_ControlPointList.size() >= 10)
		{
			m_pPointController->CalculateLSM(3);

			for (int ii = 0; ii < m_pPointController->m_ControlPointList.size(); ii++)
			{
				CString strNum, strBaseX, strBaseY, strWarpX, strWarpY, strPreX, strPreY, strErrorX, strErrorY, strError;
				strNum.Format(_T("%d"), ii + 1);
				strBaseX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.x);
				strBaseY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].BasePoint.y);
				strWarpX.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.x);
				strWarpY.Format(_T("%d"), m_pPointController->m_ControlPointList[ii].WarpPoint.y);

				double dPreX = 0;
				double dPreY = 0;

				m_pPointController->CalculatePre(m_pPointController->m_ControlPointList[ii].BasePoint, dPreX, dPreY, 3);

				double dErrorX = dPreX - m_pPointController->m_ControlPointList[ii].WarpPoint.x;
				double dErrorY = dPreY - m_pPointController->m_ControlPointList[ii].WarpPoint.y;

				strPreX.Format(_T("%.2f"), dPreX);
				strPreY.Format(_T("%.2f"), dPreY);

				strErrorX.Format(_T("%.2f"), dErrorX);
				strErrorY.Format(_T("%.2f"), dErrorY);
	
				strError.Format(_T("%.2f"), sqrt(dErrorX * dErrorX + dErrorY * dErrorY));

				m_PointList.InsertItem(ii, strNum);
				m_PointList.SetItemText(ii, 1, strBaseX);
				m_PointList.SetItemText(ii, 2, strBaseY);
				m_PointList.SetItemText(ii, 3, strWarpX);
				m_PointList.SetItemText(ii, 4, strWarpY);
				m_PointList.SetItemText(ii, 5, strPreX);
				m_PointList.SetItemText(ii, 6, strPreY);
				m_PointList.SetItemText(ii, 7, strErrorX);
				m_PointList.SetItemText(ii, 8, strErrorY);
				m_PointList.SetItemText(ii, 9, strError);
			}
		}
	}
	m_pPointController->DrawPoint();
}



void ControlPointDlg::OnItemchangedListPoint(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

	if (pNMLV->uNewState & LVIS_SELECTED)
	{
		iItemNum = pNMLV->iItem;

		// select item pNMLV->iItem;
		/*CString s;
		s.Format(_T("Selected: %lu"), pNMLV->iItem);
		MessageBox(s);*/
	}
	*pResult = 0;
}

void ControlPointDlg::OnBnClickedButtonPredict()
{
	int order = nIndex + 1;
	if (m_pPointController->m_ControlPointList.size() >= m_pPointController->LSM.get_vector_length(order))
	{
		m_pPointController->PredictPoint(order);
	}
	else
	{
		CString str;
		str.Format(_T("控制点个数不足%d个，无法预测"), m_pPointController->LSM.get_vector_length(order));
		AfxMessageBox(str);
	}
}


void ControlPointDlg::OnSelchangeComboDegree()
{
	nIndex = m_Combo.GetCurSel();
	DisplayPoint();

	// TODO: 在此添加控件通知处理程序代码
}


void ControlPointDlg::OnCpfileout()
{
	if (nIndex == 0)
	{
		if (m_pPointController->m_ControlPointList.size() < 3)
		{
			AfxMessageBox(_T("控制点个数不足三个，无法无法导出"));
			return;
		}
	}
	else if (nIndex == 1)
	{
		if (m_pPointController->m_ControlPointList.size() < 6)
		{
			AfxMessageBox(_T("控制点个数不足六个，无法无法导出"));
			return;
		}
	}
	else if (nIndex == 2)
	{
		if (m_pPointController->m_ControlPointList.size() < 10)
		{
			AfxMessageBox(_T("控制点个数不足十个，无法无法导出"));
			return;
		}
	}

	CString filename;
	LPCTSTR szFilter = _T("bmp Files(*.bmp)|*.bmp|");		//提示保存文件的类型
	CFileDialog output_img(FALSE, NULL, NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilter);		// CFileDialog的第一个参数标明是浏览(打开，TRUE)还是保存（FALSE）


	if (output_img.DoModal() == IDOK)
	{
		filename = output_img.GetPathName();		//保存文件的路径到filename变量中
		if (filename.Right(4) != _T(".bmp"))
			filename += _T(".bmp");
	}

	m_pPointController->OutputBmp(filename);

	AfxMessageBox(_T("Done"));
}


void ControlPointDlg::OnInputconpoint()
{
	CString filename;
	LPCTSTR szFilter = _T("Txt Files (*.txt)|*.txt|All Files (*.*)|*.*|");		//提示保存文件的类型
	CFileDialog output_img(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST, szFilter);		// CFileDialog的第一个参数标明是浏览(打开，TRUE)还是保存（FALSE）

	if (output_img.DoModal() == IDOK)
	{
		filename = output_img.GetPathName();		//保存文件的路径到filename变量中
	}// TODO: 在此添加命令处理程序代码

	if (filename.Right(4) != _T(".txt"))
		filename = filename + _T(".txt");

	m_pPointController->PutinControlPoint(filename, 0);

	DisplayPoint();
}


void ControlPointDlg::OnOutputconpoint()
{
	CString filename;
	LPCTSTR szFilter = _T("Txt Files (*.txt)|*.txt|All Files (*.*)|*.*|");		//提示保存文件的类型
	CFileDialog output_img(FALSE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST, szFilter);		// CFileDialog的第一个参数标明是浏览(打开，TRUE)还是保存（FALSE）

	if (output_img.DoModal() == IDOK)
	{
		filename = output_img.GetPathName();		//保存文件的路径到filename变量中
	}// TODO: 在此添加命令处理程序代码

	if (filename.Right(4) != _T(".txt"))
		filename = filename + _T(".txt");

	m_pPointController->PutoutControlPoint(filename);

	AfxMessageBox(_T("导出成功！"));

}


void ControlPointDlg::OnAddconpoint()
{
	CString filename;
	LPCTSTR szFilter = _T("Txt Files (*.txt)|*.txt|All Files (*.*)|*.*|");		//提示保存文件的类型
	CFileDialog output_img(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST, szFilter);		// CFileDialog的第一个参数标明是浏览(打开，TRUE)还是保存（FALSE）

	if (output_img.DoModal() == IDOK)
	{
		filename = output_img.GetPathName();		//保存文件的路径到filename变量中
	}// TODO: 在此添加命令处理程序代码

	if (filename.Right(4) != _T(".txt"))
		filename = filename + _T(".txt");

	m_pPointController->PutinControlPoint(filename, 1);

	DisplayPoint();
}
